﻿using AutoTest.Business.Dto.UserInfo;
using AutoTest.Business.IServices;
using AutoTest.Business.IServices.Common;
using AutoTest.Business.Model;
using AutoTest.Business.Options;
using AutoTest.Business.Vo.Product;
using AutoTest.Business.Vo.UserInfo;
using AutoTest.Business.Vo.UserPlanConfig;
using AutoTest.Common;
using AutoTest.Common.Extension;
using AutoTest.Common.UtilsHelper;
using AutoTest.Domain;
using AutoTest.Domain.Entities;
using AutoTest.Domain.Enums;
using AutoTest.Framework.Exceptions;
using AutoTest.Framework.Extensions;
using AutoTest.Framework.Ioc;
using AutoTest.Framework.Pager;
using AutoTest.Repository.RepositoryExtension;
using EasyTool;
using Mapster;
using Org.BouncyCastle.Asn1.Mozilla;
using SqlSugar;

namespace AutoTest.Business.Services
{
    /// <summary>
    /// 用户服务
    /// </summary>
    public class UserInfoService(ISqlSugarClient db, IJwtService jwtService, ISettingService settingService) : IUserService, IScoped
    {

        /// <summary>
        /// 数据库
        /// </summary>
        protected readonly ISqlSugarClient _db = db;
        /// <summary>
        /// Jwt服务
        /// </summary>
        private readonly IJwtService _jwtService = jwtService;
        private readonly ISettingService _settingService = settingService;


        /// <summary>
        /// 检查是否有此用户
        /// </summary>
        /// <param name="model"></param>
        /// <param name="updateUser"></param>
        /// <returns></returns>
        public async Task<UserInfo> CheckUserInfoAsync(OpenUserInfoModel model, bool updateUser)
        {
            OpenInfo openInfo = null!;
            long userid = IdHelper.NextId();

            #region 处理OpenInfo
            if (model.UnionId.IsNotEmpty())
            {
                openInfo = await _db.Queryable<OpenInfo>().FirstAsync(c => c.UnionId == model.UnionId);
            }
            if (openInfo.IsNull())
            {
                openInfo = await _db.Queryable<OpenInfo>().FirstAsync(c => c.OpenId == model.OpenId);
            }
            if (openInfo.IsNull())
            {
                return null!;
            }

            #endregion

            userid = openInfo.UserId;
            var user = await _db.Queryable<UserInfo>().FirstAsync(c => c.Id == userid);
            if (user != null && updateUser)
            {
                user.IconUrl = model.HeadImgUrl.IsEmpty() ? user.IconUrl : model.HeadImgUrl;
                user.NickName = model.NickName.IsEmpty() ? user.NickName : model.NickName;
                user.Province = model.Province.IsEmpty() ? user.Province : model.Province;
                user.City = model.City.IsEmpty() ? user.City : model.City;
                user.Country = model.Country.IsEmpty() ? user.Country : model.Country;
                await _db.Updateable(user).ExecuteCommandAsync();

            }
            return user!;
        }


        /// <summary>
        /// 登录，其实就是生成tkn并记录
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public async Task<LoginUserVo> LoginUserAsync(UserInfo userInfo)
        {
            var vo = userInfo.Adapt<LoginUserVo>();

            vo.OpenInfos = (await _db.Queryable<OpenInfo>().Where(c => c.UserId == userInfo.Id).ToListAsync()).Adapt<List<OpenInfoVo>>();

            var relations = await _db.Queryable<UserProductRelation>().Where(t => t.UserId == userInfo.Id).ToListAsync();
            vo.Products = relations;
            vo.Token = _jwtService.Generate(vo);
            return vo;
        }

        #region 用户管理

        /// <summary>
        /// 分页搜索
        /// </summary>
        /// <param name="searchDto"></param>
        /// <returns></returns>
        public async Task<PagedList<UserInfoListVo>> PageSearchUserInfoListAsync(UserInfoPageSearchDto searchDto)
        {
            var query = FilterUserQuery(_db.Queryable<UserInfo>(), searchDto);
            var (data, count) = await query.OrderByDescending(t=>t.CreateTime).ToPageListAsync(searchDto);
            var voList = data.Adapt<List<UserInfoListVo>>();
            var userIds = data.Select(t => t.Id).ToList();
            var relations = await _db.Queryable<UserProductRelation>().Where(t => userIds.Contains(t.UserId)).ToListAsync();
            voList = voList.GroupJoin(relations, t => t.Id, t => t.UserId, (u, relationList) =>
            {
                u.Products = relationList.ToList();
                return u;
            }).ToList();
            return searchDto.ToPagedList(voList, count);
        }

        /// <summary>
        /// 获取用户详情
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<UserInfoDetailVo> GetUserInfoDetailAsync(long userid)
        {
            var userInfoEntity = await _db.Queryable<UserInfo>().FirstAsync(t => t.Id == userid)
                ?? throw new BusinessException("用户不存在");
            var vo = userInfoEntity.Adapt<UserInfoDetailVo>();
            var relations = await _db.Queryable<UserProductRelation>().Where(t => t.UserId == userid).ToListAsync();
            vo.Products = relations;
            return vo;
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="addDto"></param>
        /// <returns></returns>
        public async Task<UserInfoDetailVo> AddUserInfoAsync(UserInfoAddDto addDto)
        {
            if (addDto.UserName.IsEmpty()) addDto.UserName = addDto.Phone;
            if (!addDto.Sex.HasValue) addDto.Sex = EnumSex.Unknown;
            var userInfo = addDto.Adapt<UserInfo>();
            if (addDto.Password.IsEmpty())
            {
                var appsetting = await _settingService.GetSettingOptionAsync<AppSettingOption>(AppConsts.APPSETTING_APP);
                var defaultPwd = $"{appsetting?.DefaultPassword ?? ""}_{addDto.Phone}"; //EncryptHelper.Md532($"{appsetting?.DefaultPassword ?? ""}_{addDto.Phone}");
                userInfo.Password = defaultPwd;
            }
            else
            {
                userInfo.Password = addDto.Password;
            }
            userInfo.CreateTime = DateTime.Now;
            userInfo.Id = IdHelper.NextId();

            var old = await _db.Queryable<UserInfo>().FirstAsync(t => t.UserName == userInfo.UserName);
            if (old != null) throw new BusinessException($"用户名【{userInfo.UserName}】已经存在");

            if (userInfo.UserName.IsEmpty()) userInfo.UserName = userInfo.Phone;
            _db.Insertable(userInfo).AddQueue();

            if ((addDto.Products?.Count ?? 0) > 0)
            {
                var productList = addDto.Products?.Select(t => new UserProductRelation()
                {
                    Id = IdUtil.SnowflakeId(),
                    ProductId = t.ProductId,
                    ProductName = t.ProductName,
                    UserId = userInfo.Id,
                    ValidTime = t.ValidTime,
                }).ToList();
                _db.Insertable(productList).AddQueue();
            }

            await _db.SaveQueuesAsync();

            var vo = userInfo.Adapt<UserInfoDetailVo>();
            return vo;
        }

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="editDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<UserInfoDetailVo> EditUserInfoAsync(long id, UserInfoAddDto editDto)
        {
            var userInfoEntity = await _db.Queryable<UserInfo>().FirstAsync(t => t.Id == id) ?? throw new BusinessException("用户不存在");
            userInfoEntity.CopyFrom(editDto as UserInfoAddDto);
            await _db.Updateable(userInfoEntity).ExecuteCommandAsync();

            var vo = userInfoEntity.Adapt<UserInfoDetailVo>();

            await _db.Deleteable<UserProductRelation>().Where(t => t.UserId == id).ExecuteCommandAsync();
            if ((editDto.Products?.Count ?? 0) > 0)
            {
                var productList = editDto.Products?.Select(t => new UserProductRelation()
                {
                    Id = IdUtil.SnowflakeId(),
                    ProductId = t.ProductId,
                    ProductName = t.ProductName,
                    UserId = userInfoEntity.Id,
                    ValidTime = t.ValidTime,
                }).ToList();
                await _db.Insertable(productList).ExecuteCommandAsync();

                vo.Products = productList ?? [];
            }
            return vo;
        }

        /// <summary>
        /// 修改用户状态
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<UserInfoDetailVo> ChangeUserStatusAsync(long userid, EnumStatus status)
        {
            var userInfoEntity = await _db.Queryable<UserInfo>().FirstAsync(t => t.Id == userid) ?? throw new BusinessException("用户不存在");
            userInfoEntity.Status = status;
            await _db.Updateable(userInfoEntity).UpdateColumns(nameof(userInfoEntity.Status)).ExecuteCommandAsync();
            var vo = userInfoEntity.Adapt<UserInfoDetailVo>();
            return vo;

        }


        private ISugarQueryable<UserInfo> FilterUserQuery(ISugarQueryable<UserInfo> query, UserInfoSearchDto searchDto)
        {
            if (searchDto != null)
            {
                query.WhereIF(searchDto.Phone.IsNotEmpty(), t => t.Phone == searchDto.Phone)
                    .WhereIF(searchDto.UserName.IsNotEmpty(), t => t.UserName == searchDto.UserName)
                    .WhereIF(searchDto.Sex.HasValue, t => t.Sex == searchDto.Sex!.Value)
                    .WhereIF(searchDto.Keyword.IsNotEmpty(), t => t.UserName.Contains(searchDto.Keyword) || t.Phone.Contains(searchDto.Keyword));
            }
            return query;
        }

        #endregion

        #region 用户方案配置
        /// <summary>
        /// 添加用户方案配置
        /// </summary>
        /// <param name="addDto"></param>
        /// <returns></returns>
        public async Task AddUserPlanConfigAsync(UserPlanConfigAddDto addDto)
        {
            if (!string.IsNullOrWhiteSpace(addDto?.Key) && !string.IsNullOrWhiteSpace(addDto.Config))
            {
                var entity = new UserPlanConfig()
                {
                    Id = IdUtil.SnowflakeId(),
                    Config = addDto.Config,
                    Key = addDto.Key,
                    Name = addDto.Name,

                };
                await _db.Insertable(entity).ExecuteCommandAsync();
            }
        }
        /// <summary>
        /// 获取配置
        /// </summary>
        /// <param name="configId"></param>
        /// <returns></returns>
        public async Task<UserPlanConfigVo> GetUserPlanConfigAsync(long configId)
        {
            var planConfig = await _db.Queryable<UserPlanConfig>().FirstAsync(t => t.Id == configId) ?? throw new BusinessException($"未能找到编码为【{configId}】的配置");
            var vo = planConfig.Adapt<UserPlanConfigVo>();
            return vo;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<LoginUserVo> UserLoginAsync(UserLoginDto loginDto)
        {
            var userinfo = (await _db.Queryable<UserInfo>().FirstAsync(t => t.
                    UserName == loginDto.UserName 
                    && t.Password == loginDto.Password
                    && t.Status == EnumStatus.Enable
                    ))?? throw new BusinessException("用户名或者密码错误");
            var vo = await LoginUserAsync(userinfo);
            return vo;
        }
        /// <summary>
        /// 查询当前用户开通的产品
        /// </summary>
        /// <returns></returns>
        public async Task<UserProductVo> GetCurrentUserProductsAsync()
        {
            var user = _jwtService.GetCurrentUser() ?? throw new UnauthorizedAccessException(); ;
            var vo = new UserProductVo() { 
                UserId = user.Id,
                UserName = user.UserName
            };
            var productList = await _db.Queryable<UserProductRelation>()
                .LeftJoin<Product>((r, p) => r.ProductId == p.Id)
                .Where((r, p) => r.UserId == user.Id 
                && p.Status == EnumStatus.Enable
                && r.ValidTime.Date >= DateTime.Now.Date)
                .Select((r, p) => new ProductValidListVo() { 
                    FrontPath = p.FrontPath,
                    BriefDesc = p.BriefDesc,
                    Id = p.Id,
                    ProductName = p.ProductName,
                    ListIndex = p.ListIndex,
                    Status  = EnumStatus.Enable,
                    UpdateBy = p.UpdateBy,
                    UpdateTime = p.UpdateTime,
                    ValidTime = r.ValidTime,
                }).ToListAsync();
            vo.Products = productList;
            return vo;
        }
        /// <summary>
        /// 检查用户是否具有产品权限
        /// </summary>
        /// <param name="frontPath"></param>
        /// <returns></returns>
        public async Task CheckUserProductAsync(string frontPath)
        {
            var user = _jwtService.GetCurrentUser() ?? throw new UnauthorizedAccessException();
            var result = await _db.Queryable<UserProductRelation>()
                .LeftJoin<Product>((r, p) => r.ProductId == p.Id)
                .Where((r, p) => r.UserId == user.Id
                && p.Status == EnumStatus.Enable
                && r.ValidTime.Date >= DateTime.Now.Date 
                && p.FrontPath.StartsWith(frontPath))
                .AnyAsync();
            if (!result) throw new BusinessException("未开通此产品，请联系销售开通！");
        }
        #endregion
    }
}
